package com.example.tinylog_ohos;


import com.example.tinylog_ohos.slice.MainAbilitySlice;
import ohos.aafwk.ability.Ability;
import ohos.aafwk.content.Intent;
import ohos.agp.components.Button;
import ohos.agp.components.Component;
import ohos.agp.window.dialog.CommonDialog;
import ohos.agp.window.dialog.IDialog;
import org.pmw.tinylog_test.*;
import org.pmw.tinylog_test.writers.LogEntryValue;
import org.pmw.tinylog_test.writers.Writer;

import java.lang.reflect.Field;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.EnumSet;
import java.util.Set;

import static com.example.tinylog_ohos.StringMatchers.containsPattern;
import static com.example.tinylog_ohos.StringMatchers.matchesPattern;


public class MainAbility extends Ability {
    private Button mTestLoggingLevel, mTestCustomLoggingLevel, mTestTrace, mTestDebug, mTestInfo, mTestWarning, mTestError, mTestOutputWithStackTraceDeep, mTestOutputWithStackTraceElement, mTestOutputWithClassName, mTestOutputIfWriterHasSeverityLevel, mTestLogEntryWithProcessId, mTestLogEntryWithThread, mTestLogEntryWithThreadId, mTestLogEntryWithFullyQualifiedClassName, mTestLogEntryWithPackageName, mTestLogEntryWithClassName, mTestLogEntryWithMethodName, mTestLogEntryWithfileName, mTestLogEntryWithLineNumber, mTestLogEntryWithLoggingLevel, mTestLogEntryWithDate, mTestLogEntryWithMessage, mTestFullLogEntry, mTestExceptions, mTestConfiguration, mTestErrorWhileCallingSunReflection, mTestErrorWhileGettingSingleStackTraceElement;

    @Override
    public void onStart(Intent intent) {
        super.onStart(intent);
        super.setMainRoute(MainAbilitySlice.class.getName());
        super.setUIContent(ResourceTable.Layout_ability_main);
        initComponent();
    }

    private void initComponent() {
        mTestLoggingLevel = (Button) findComponentById(ResourceTable.Id_testLoggingLevel);
        mTestLoggingLevel.setClickedListener(new Component.ClickedListener() {
            @Override
            public void onClick(Component Component) {
                Configurator.defaultConfig().level(Level.TRACE).activate();
                Logger.info("mtestLoggingLevel" + Level.TRACE + "       " + Logger.getLevel());

                Configurator.currentConfig().level(Level.OFF).activate();
                Logger.info("mtestLoggingLevel" + Level.OFF + "       " + Logger.getLevel());


                Configurator.currentConfig().level(Level.ERROR).activate();
                Logger.info("mtestLoggingLevel" + Level.ERROR + "       " + Logger.getLevel());

                Configurator.currentConfig().level(Level.DEBUG).activate();
                Logger.info("mtestLoggingLevel" + Level.DEBUG + "       " + Logger.getLevel());


                Configurator.currentConfig().level(null).activate();
                Logger.info("mtestLoggingLevel" + Level.OFF + "       " + Logger.getLevel());

            }
        });
        mTestCustomLoggingLevel = (Button) findComponentById(ResourceTable.Id_testCustomLoggingLevel);
        mTestCustomLoggingLevel.setClickedListener(new Component.ClickedListener() {
            @Override
            public void onClick(Component Component) {
                Configurator.defaultConfig().level("a", Level.TRACE).level("a.b", Level.INFO).activate();

                Logger.info("mTestCustomLoggingLevel" + Level.TRACE + Logger.getLevel("a"));
                Logger.info("mTestCustomLoggingLevel" + Level.INFO + Logger.getLevel("a.b"));
                Logger.info("mTestCustomLoggingLevel" + Level.TRACE + Logger.getLevel("a.c"));
                Logger.info("mTestCustomLoggingLevel" + Level.INFO + Logger.getLevel("a.b.d"));
                Logger.info("mTestCustomLoggingLevel" + Level.TRACE + Logger.getLevel("a.c.d"));

                Configurator.defaultConfig().level(Logger.class.getPackage(), Level.TRACE).activate();

                Logger.info("mTestCustomLoggingLevel" + Level.TRACE + Logger.getLevel(Logger.class.getPackage()));
                Logger.info("mTestCustomLoggingLevel" + Level.TRACE + Logger.getLevel(Logger.class));

                Configurator.defaultConfig().level(Logger.class, Level.TRACE).activate();

                Logger.info("mTestCustomLoggingLevel" + Level.INFO + Logger.getLevel(Logger.class.getPackage()));
                Logger.info("mTestCustomLoggingLevel" + Level.TRACE + Logger.getLevel(Logger.class));
            }

        });
        mTestTrace = (Button) findComponentById(ResourceTable.Id_testTrace);
        mTestTrace.setClickedListener(new Component.ClickedListener() {
            @Override
            public void onClick(Component Component) {
                Configurator.defaultConfig().level(Level.TRACE).activate();
                Logger.info("mTestTrace" + Level.TRACE + "       " + Logger.getLevel());
                Logger.trace("mTestTrace !");
            }
        });
        mTestDebug = (Button) findComponentById(ResourceTable.Id_testDebug);
        mTestDebug.setClickedListener(new Component.ClickedListener() {
            @Override
            public void onClick(Component Component) {
                Configurator.currentConfig().level(Level.DEBUG).activate();
                Logger.info("mTestDebug" + Level.DEBUG + "       " + Logger.getLevel());
                Logger.debug("mTestDebug !");
            }
        });
        mTestInfo = (Button) findComponentById(ResourceTable.Id_testInfo);
        mTestInfo.setClickedListener(new Component.ClickedListener() {
            @Override
            public void onClick(Component Component) {
                org.pmw.tinylog_test.Logger.info("mTestInfo !");
            }
        });
        mTestWarning = (Button) findComponentById(ResourceTable.Id_testWarning);
        mTestWarning.setClickedListener(new Component.ClickedListener() {
            @Override
            public void onClick(Component Component) {
                Logger.warn("mTestWarning !");
            }
        });
        mTestError = (Button) findComponentById(ResourceTable.Id_testError);
        mTestError.setClickedListener(new Component.ClickedListener() {
            @Override
            public void onClick(Component Component) {
                Logger.error("mTestError !");
            }
        });
        mTestOutputWithStackTraceDeep = (Button) findComponentById(ResourceTable.Id_testOutputWithStackTraceDeep);
        mTestOutputWithStackTraceDeep.setClickedListener(new Component.ClickedListener() {
            @Override
            public void onClick(Component Component) {
                Logger.info("mTestOutputWithStackTraceDeep");
                Logger.info("mTestOutputWithStackTraceDeep" + "         " + Logger.class.getName());
                Logger.info("mTestOutputWithStackTraceDeep" + "         " + Logger.DEEP_OF_STACK_TRACE, Level.DEBUG);

                Logger.info("mTestOutputWithStackTraceDeep" + "         " + Logger.getLevel() + Level.INFO);
                Logger.info("mTestOutputWithStackTraceDeep" + Logger.DEEP_OF_STACK_TRACE + Level.INFO);
                StoreWriter writer = new StoreWriter(LogEntryValue.LEVEL, LogEntryValue.CLASS);
                Configurator.defaultConfig().writer(writer).level(Level.DEBUG).activate();

                /* Test logging of class */

                Logger.info("mTestOutputWithStackTraceDeep" + Logger.DEEP_OF_STACK_TRACE + "         " + Level.INFO);
                LogEntry logEntry = writer.consumeLogEntry();


                Logger.info("mTestOutputWithStackTraceDeep" + "         " + Logger.class.getName());
                Logger.info("mTestOutputWithStackTraceDeep" + "         " + Logger.getLevel() + Level.INFO);


                writer = new StoreWriter(LogEntryValue.LEVEL, LogEntryValue.MESSAGE, LogEntryValue.EXCEPTION);
                Configurator.defaultConfig().writer(writer).level(Level.INFO).activate();
                Logger.info("mTestOutputWithStackTraceDeep" + "         " + Logger.DEEP_OF_STACK_TRACE, Level.DEBUG);

                if (writer.consumeLogEntry() == null) {
                    return;
                }


            }
        });
        mTestOutputWithStackTraceElement = (Button) findComponentById(ResourceTable.Id_testOutputWithStackTraceElement);
        mTestOutputWithStackTraceElement.setClickedListener(new Component.ClickedListener() {
            @Override
            public void onClick(Component Component) {

                Configurator.defaultConfig().level(Level.TRACE).activate();
                Logger.info("mTestOutputWithStackTraceElement" + Level.INFO, Logger.getLevel());

                Exception exception = new Exception();
                Logger.info("mTestOutputWithStackTraceElement" + Level.ERROR + Logger.getLevel());
                Logger.info("mTestOutputWithStackTraceElement" + exception);
                StackTraceElement stackTraceElement = new StackTraceElement("com.test.MyClass", "?", "?", -1);

                /* Test logging without writer */

                Configurator.defaultConfig().writer(null).activate();
                Logger.info("mTestOutputWithStackTraceElement" + stackTraceElement, Level.INFO);

                /* Initialize writer */

                StoreWriter writer = new StoreWriter(LogEntryValue.LEVEL, LogEntryValue.CLASS);
                Configurator.defaultConfig().writer(writer).activate();

                /* Test logging of class */

                Configurator.currentConfig().level(Level.DEBUG).activate();

                Logger.output(stackTraceElement, Level.INFO, null, "Hello!", new Object[0]);
                LogEntry logEntry = writer.consumeLogEntry();
                Logger.info("mTestOutputWithStackTraceElement" + Level.INFO + "        " + Logger.getLevel());

                /* Test logging of plain texts */

                writer = new StoreWriter(LogEntryValue.LEVEL, LogEntryValue.MESSAGE);
                Configurator.currentConfig().writer(writer).level(Level.INFO).activate();

                Logger.output(stackTraceElement, Level.DEBUG, null, "Hello!", new Object[0]);
                Logger.info(writer.consumeLogEntry());

                Logger.output(stackTraceElement, Level.INFO, null, "Hello {}!", new Object[]{"World"});
                logEntry = writer.consumeLogEntry();
                Logger.info("mTestOutputWithStackTraceElement" + Level.INFO + Logger.getLevel());

                /* Test logging of exceptions */

                writer = new StoreWriter(LogEntryValue.LEVEL, LogEntryValue.MESSAGE, LogEntryValue.EXCEPTION);
                Configurator.currentConfig().writer(writer).level(Level.INFO).activate();



                Logger.output(stackTraceElement, Level.WARNING, exception, null, new Object[0]);
                logEntry = writer.consumeLogEntry();
                Logger.info("mTestOutputWithStackTraceElement" + Level.WARNING + Logger.getLevel());
                Logger.info("mTestOutputWithStackTraceElement" + exception);

                Logger.output(stackTraceElement, Level.ERROR, exception, "Test", new Object[0]);
                Logger.info("mTestOutputWithStackTraceElement" + Level.ERROR + Logger.getLevel());
                Logger.info("mTestOutputWithStackTraceElement" + exception);

                /* Test different logging level of an particular package */

                Configurator.currentConfig().level("com.test", Level.DEBUG).activate();

                Logger.output(stackTraceElement, Level.DEBUG, null, "Hello!", new Object[0]);
                logEntry = writer.consumeLogEntry();
                Logger.info("mTestOutputWithStackTraceElement" + Level.DEBUG + Logger.getLevel());

                /* Test failure of creating log entry */

                Configurator.currentConfig().level("com.test", null).activate();

                Logger.info(writer.consumeLogEntry());

                /* Test failure of writing log entry */


                Logger.output(stackTraceElement, Level.ERROR, null, "Hello!", new Object[0]);

                /* Test using writing thread */

                Configurator.currentConfig().writer(writer).writingThread(null).activate();
                WritingThread writingThread = findWritingThread();
                Logger.info(writingThread);

                Logger.output(stackTraceElement, Level.INFO, null, "Hello!", new Object[0]);
                Logger.info(writer.consumeLogEntry());
                writingThread.shutdown();
                try {
                    writingThread.join();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                logEntry = writer.consumeLogEntry();
                Logger.info("mTestOutputWithStackTraceElement" + Level.INFO, Logger.getLevel());
            }
        });


        mTestOutputWithClassName = (Button) findComponentById(ResourceTable.Id_testOutputWithClassName);
        mTestOutputWithClassName.setClickedListener(new Component.ClickedListener() {
            @Override
            public void onClick(Component Component) {
                Configurator.defaultConfig().level(Level.INFO).activate();
                Logger.info("mTestOutputWithClassName" + org.pmw.tinylog_test.Logger.getLevel());
                Logger.info("mTestOutputWithClassName!" + MainAbility.class.getName());
            }
        });
        mTestOutputIfWriterHasSeverityLevel = (Button) findComponentById(ResourceTable.Id_testOutputIfWriterHasSeverityLevel);
        mTestOutputIfWriterHasSeverityLevel.setClickedListener(new Component.ClickedListener() {
            @Override
            public void onClick(Component Component) {
                StoreWriter writer = new StoreWriter(LogEntryValue.MESSAGE);
                Configurator.defaultConfig().writer(writer, Level.INFO).level(Level.TRACE).activate();

                Configurator.defaultConfig().level(Level.TRACE).activate();
                Logger.info("mTestOutputIfWriterHasSeverityLevel" + Level.TRACE + "   1    " + Logger.getLevel());

                Configurator.currentConfig().level(Level.OFF).activate();
                Logger.info("mTestOutputIfWriterHasSeverityLevel" + Level.OFF + "    2   " + Logger.getLevel());


                Configurator.currentConfig().level(Level.ERROR).activate();
                Logger.info("mTestOutputIfWriterHasSeverityLevel" + Level.ERROR + "   3    " + Logger.getLevel());

                Configurator.currentConfig().level(Level.DEBUG).activate();
                Logger.info("mTestOutputIfWriterHasSeverityLevel" + Level.DEBUG + "    4   " + Logger.getLevel());


                Configurator.currentConfig().level(null).activate();
                Logger.info("mTestOutputIfWriterHasSeverityLevel" + Level.OFF + "    4   " + Logger.getLevel());
            }
        });
        mTestLogEntryWithProcessId = (Button) findComponentById(ResourceTable.Id_testLogEntryWithProcessId);
        mTestLogEntryWithProcessId.setClickedListener(new Component.ClickedListener() {
            @Override
            public void onClick(Component Component) {
                Configurator.defaultConfig().level(Level.INFO).activate();

                Logger.info("mTestLogEntryWithProcessId");
            }
        });
        mTestLogEntryWithThread = (Button) findComponentById(ResourceTable.Id_testLogEntryWithThread);
        mTestLogEntryWithThread.setClickedListener(new Component.ClickedListener() {
            @Override
            public void onClick(Component Component) {
                Configurator.defaultConfig().level(Level.INFO).activate();

                Logger.info("mTestLogEntryWithThread");
                Thread thread = new Thread(new Runnable() {
                    @Override
                    public void run() {

                    }
                });
                thread.run();
                thread.setName("mTestLogEntryWithThread");
                thread.setPriority(Thread.MAX_PRIORITY);
                StoreWriter writer = new StoreWriter(LogEntryValue.THREAD, LogEntryValue.RENDERED_LOG_ENTRY);
                Configurator.defaultConfig().writer(writer).level(Level.INFO).formatPattern("{thread}").activate();

                Logger.info("mTestLogEntryWithThread   name"+thread.getName()+"state     "+thread.getState()+"Priority    "+thread.getPriority());

            }
        });
        mTestLogEntryWithThreadId = (Button) findComponentById(ResourceTable.Id_testLogEntryWithThreadId);
        mTestLogEntryWithThreadId.setClickedListener(new Component.ClickedListener() {
            @Override
            public void onClick(Component Component) {
                Configurator.defaultConfig().level(Level.INFO).activate();
                Logger.info("mTestLogEntryWithThreadId");

                Logger.info("mTestLogEntryWithThreadId" + Thread.currentThread());

            }
        });
        mTestLogEntryWithFullyQualifiedClassName = (Button) findComponentById(ResourceTable.Id_testLogEntryWithFullyQualifiedClassName);
        mTestLogEntryWithFullyQualifiedClassName.setClickedListener(new Component.ClickedListener() {
            @Override
            public void onClick(Component Component) {
                Configurator.defaultConfig().level(Level.INFO).activate();

                Logger.info("mTestLogEntryWithFullyQualifiedClassName");
                Logger.info("mTestLogEntryWithFullyQualifiedClassName" + Logger.class.getName());
                Logger.info("mTestLogEntryWithFullyQualifiedClassName" + Logger.class.getName() + EnvironmentHelper.getNewLine());



            }
        });
        mTestLogEntryWithPackageName = (Button) findComponentById(ResourceTable.Id_testLogEntryWithPackageName);
        mTestLogEntryWithPackageName.setClickedListener(new Component.ClickedListener() {
            @Override
            public void onClick(Component Component) {
                Configurator.defaultConfig().level(Level.INFO).activate();

                Logger.info("mTestLogEntryWithPackageName");
                Logger.output(new StackTraceElement("mTestLogEntryWithPackageName", "unknown", "unknown", -1), Level.INFO, null, "Hello", new Object[0]);



                Logger.info(Logger.class.getName());
                Logger.info(Logger.class.getPackage().getName() + EnvironmentHelper.getNewLine());

                Logger.info("mTestLogEntryWithPackageName");
                Logger.info("mTestLogEntryWithPackageName" + EnvironmentHelper.getNewLine());

                Logger.output(new StackTraceElement("MyClass", "unknown", "unknown", -1), Level.INFO, null, "Hello", new Object[0]);

            }
        });
        mTestLogEntryWithClassName = (Button) findComponentById(ResourceTable.Id_testLogEntryWithClassName);
        mTestLogEntryWithClassName.setClickedListener(new Component.ClickedListener() {
            @Override
            public void onClick(Component Component) {
                Configurator.defaultConfig().level(Level.INFO).activate();

                Logger.info("mTestLogEntryWithClassName");



                Logger.info(Logger.class.getName());
                Logger.info(Logger.class.getSimpleName() + EnvironmentHelper.getNewLine());

                Logger.output(new StackTraceElement("com.test.MyClass", "unknown", "unknown", -1), Level.INFO, null, "Hello", new Object[0]);

                Logger.info("com.test.MyClass");
                Logger.info("mTestLogEntryWithClassName" + EnvironmentHelper.getNewLine());

                Logger.output(new StackTraceElement("mTestLogEntryWithClassName", "unknown", "unknown", -1), Level.INFO, null, "Hello", new Object[0]);

                Logger.info("mTestLogEntryWithClassName");
                Logger.info("mTestLogEntryWithClassName" + EnvironmentHelper.getNewLine());
            }
        });
        mTestLogEntryWithMethodName = (Button) findComponentById(ResourceTable.Id_testLogEntryWithMethodName);
        mTestLogEntryWithMethodName.setClickedListener(new Component.ClickedListener() {
            @Override
            public void onClick(Component Component) {

                Configurator.defaultConfig().level(Level.INFO).activate();

                Logger.info("mTestLogEntryWithMethodName"+Logger.getConfiguration().toString());

            }
        });
        mTestLogEntryWithfileName = (Button) findComponentById(ResourceTable.Id_testLogEntryWithFileName);
        mTestLogEntryWithfileName.setClickedListener(new Component.ClickedListener() {
            @Override
            public void onClick(Component Component) {
                Configurator.defaultConfig().level(Level.INFO).activate();

                Logger.info("mTestLogEntryWithfileName");

                Logger.info("mTestLogEntryWithfileName Logger.java" + EnvironmentHelper.getNewLine());
            }
        });
        mTestLogEntryWithLineNumber = (Button) findComponentById(ResourceTable.Id_testLogEntryWithLineNumber);
        mTestLogEntryWithLineNumber.setClickedListener(new Component.ClickedListener() {
            @Override
            public void onClick(Component Component) {
                Configurator.defaultConfig().level(Level.INFO).activate();

                Logger.info("mTestLogEntryWithLineNumber");


                int lineNumber = new Throwable().getStackTrace()[0].getLineNumber() + 1;

                Logger.info("mTestLogEntryWithLineNumber" + lineNumber);
                Logger.info(lineNumber + EnvironmentHelper.getNewLine());
            }
        });
        mTestLogEntryWithLoggingLevel = (Button) findComponentById(ResourceTable.Id_testLogEntryWithLoggingLevel);
        mTestLogEntryWithLoggingLevel.setClickedListener(new Component.ClickedListener() {
            @Override
            public void onClick(Component Component) {
                Configurator.defaultConfig().level(Level.INFO).activate();

                Logger.info("mTestLogEntryWithLoggingLevel");
                Logger.info("mTestLogEntryWithLoggingLevel" + Level.INFO, Logger.getLevel());
                Logger.info("mTestLogEntryWithLoggingLevel"+Level.INFO + EnvironmentHelper.getNewLine());
            }
        });
        mTestLogEntryWithDate = (Button) findComponentById(ResourceTable.Id_testLogEntryWithDate);
        mTestLogEntryWithDate.setClickedListener(new Component.ClickedListener() {
            @Override
            public void onClick(Component Component) {
                Configurator.defaultConfig().level(Level.INFO).activate();

                Logger.info("mTestLogEntryWithDate");

                Logger.info("mTestLogEntryWithDate" + new Date().getTime());
                Logger.info("mTestLogEntryWithDate" + new SimpleDateFormat("yyyy-MM-dd").format(new Date()) + EnvironmentHelper.getNewLine());
                StoreWriter writer = new StoreWriter(LogEntryValue.DATE, LogEntryValue.RENDERED_LOG_ENTRY);
                Configurator.defaultConfig().writer(writer).level(Level.INFO).formatPattern("{date:yyyy-MM-dd}").activate();

            }

        });
        mTestLogEntryWithMessage = (Button) findComponentById(ResourceTable.Id_testLogEntryWithMessage);
        mTestLogEntryWithMessage.setClickedListener(new Component.ClickedListener() {
            @Override
            public void onClick(Component Component) {
                Configurator.defaultConfig().level(Level.INFO).activate();

                Exception exception = new Exception();
                Logger.info(exception, "mTestLogEntryWithMessage");

                Logger.info("mTestLogEntryWithMessage" + exception);
                StoreWriter writer = new StoreWriter(LogEntryValue.MESSAGE, LogEntryValue.RENDERED_LOG_ENTRY);
                boolean loggerBoolean = Configurator.defaultConfig().writer(writer).level(Level.INFO).formatPattern("{message}").activate();
                Logger.info("mTestLogEntryWithMessage", loggerBoolean);




            }
        });
        mTestFullLogEntry = (Button) findComponentById(ResourceTable.Id_testFullLogEntry);
        mTestFullLogEntry.setClickedListener(new Component.ClickedListener() {
            @Override
            public void onClick(Component Component) {
                Configurator.defaultConfig().level(Level.INFO).activate();

                Logger.info("mTestFullLogEntry" + Thread.currentThread());
                Logger.info("mTestFullLogEntry Logger.java" + Logger.class.getName());

                Logger.info("mTestFullLogEntry Logger.java", Logger.class);
                Logger.info("mTestFullLogEntry" + Level.INFO, Logger.getLevel());
                Logger.info("mTestFullLogEntry" + new Date().getTime(), 10 * 1000d /* delta of 10 seconds */);
                Logger.info("mTestFullLogEntry");
                StoreWriter writer = new StoreWriter(EnumSet.allOf(LogEntryValue.class));
                int lineNumber = new Throwable().getStackTrace()[0].getLineNumber() + 1;
                Logger.info("mTestFullLogEntry   lineNumber" + lineNumber);



//
//                Logger.info(renderedLogEntry, logEntry.getRenderedLogEntry());
            }
        });
        mTestExceptions = (Button) findComponentById(ResourceTable.Id_testExceptions);
        mTestExceptions.setClickedListener(new Component.ClickedListener() {
            @Override
            public void onClick(Component Component) {
                Configurator.defaultConfig().level(Level.ERROR).activate();

                String newLine = EnvironmentHelper.getNewLine();
                StoreWriter writer = new StoreWriter(LogEntryValue.LEVEL, LogEntryValue.EXCEPTION, LogEntryValue.RENDERED_LOG_ENTRY);

                Configurator.defaultConfig().writer(writer).level(Level.ERROR).formatPattern("{message}").maxStackTraceElements(0).activate();

                Throwable exception = new Throwable();
                Logger.error(exception);
                LogEntry logEntry = writer.consumeLogEntry();
                Logger.error("mTestExceptions" + exception);
                Logger.error("mTestExceptions" + newLine, logEntry.getRenderedLogEntry());

                exception = new Throwable("mTestExceptions");
                Logger.error(exception);
                logEntry = writer.consumeLogEntry();
                Logger.error("mTestExceptions" + exception);
                Logger.error("mTestExceptions" + newLine, logEntry.getRenderedLogEntry());

                Configurator.currentConfig().maxStackTraceElements(1).activate();

                exception = new Exception("mTestExceptions");
                Logger.error(exception);
                logEntry = writer.consumeLogEntry();
                Logger.error("mTestExceptions" + exception);
                Logger.error(logEntry.getRenderedLogEntry(), matchesPattern("java\\.lang\\.Exception\\: Test" + newLine
                        + "\tat org.pmw.tinylog_test.Logger.testExceptions\\(Logger.java:\\d*\\)" + newLine + "\t\\.\\.\\." + newLine));

                Configurator.currentConfig().maxStackTraceElements(-1).activate();

                exception = new RuntimeException(new NullPointerException());
                Logger.error(exception);
                logEntry = writer.consumeLogEntry();
                Logger.error("mTestConfiguration" + exception);
                Logger.error(logEntry.getRenderedLogEntry(), containsPattern("java\\.lang\\.RuntimeException.*" + newLine
                        + "\tat org.pmw.tinylog_test.Logger.testExceptions\\(Logger.java:\\d*\\)" + newLine));
                Logger.error(logEntry.getRenderedLogEntry(), containsPattern("Caused by: java\\.lang\\.NullPointerException" + newLine
                        + "\tat org.pmw.tinylog_test.Logger.testExceptions\\(Logger.java:\\d*\\)" + newLine));
            }
        });
        mTestConfiguration = (Button) findComponentById(ResourceTable.Id_testConfiguration);
        mTestConfiguration.setClickedListener(new Component.ClickedListener() {
            @Override
            public void onClick(Component Component) {
                Configurator.defaultConfig().level(Level.INFO).activate();

                /* Test getting and setting configuration */
                Logger.info("mTestConfiguration", Logger.getConfiguration().create().getFormatPattern());

                Configuration configuration = Configurator.defaultConfig().writer(null).formatPattern("Hello World").create();
                try {
                    Logger.setConfirguration(configuration);
                } catch (Exception e) {
                    e.printStackTrace();
                }

                /* Reset logger */

                Field field = null;
                try {
                    field = Logger.class.getDeclaredField("configuration");
                } catch (NoSuchFieldException e) {
                    e.printStackTrace();
                }
                field.setAccessible(true);
                try {
                    field.set(null, null);
                } catch (IllegalAccessException e) {
                    e.printStackTrace();
                }

                /* Call init() method only once */

                DummyWriter writer = new DummyWriter();

                configuration = Configurator.defaultConfig().writer(writer).create();
                try {
                    Logger.setConfirguration(configuration);
                } catch (Exception e) {
                    e.printStackTrace();
                }
                Logger.info("mTestConfiguration" + Logger.getConfiguration().create().getWriters());
                Logger.info("mTestConfiguration" + writer.numberOfInits);

                configuration = Configurator.defaultConfig().writer(writer).create();
                try {
                    Logger.setConfirguration(configuration);
                } catch (Exception e) {
                    e.printStackTrace();
                }
                Logger.info("mTestConfiguration    " + Logger.getConfiguration().create().getWriters());
                Logger.info("mTestConfiguration    " + writer.numberOfInits);

                writer = new DummyWriter();

                Logger.info("mTestConfiguration" + writer.numberOfInits);
                configuration = Configurator.defaultConfig().writer(writer).create();
                try {
                    Logger.setConfirguration(configuration);
                } catch (Exception e) {
                    e.printStackTrace();
                }
                Logger.info("mTestConfiguration" + Logger.getConfiguration().create().getWriters());
                Logger.info("mTestConfiguration" + writer.numberOfInits);
            }
        });
        mTestErrorWhileCallingSunReflection = (Button) findComponentById(ResourceTable.Id_testErrorWhileCallingSunReflection);
        mTestErrorWhileCallingSunReflection.setClickedListener(new Component.ClickedListener() {
            @Override
            public void onClick(Component Component) {
                Configurator.defaultConfig().level(Level.INFO).activate();

                Logger.info("mTestErrorWhileCallingSunReflection");

                Logger.info("mTestErrorWhileCallingSunReflection" + "LOGGER WARNING\\: Failed to get caller class from sun.reflect.Reflection (.+)");

                Logger.info("mTestErrorWhileCallingSunReflection" + Logger.class.getName());
                Logger.info("mTestErrorWhileCallingSunReflection" + Logger.class.getName() + EnvironmentHelper.getNewLine());
                StoreWriter writer = new StoreWriter(LogEntryValue.CLASS, LogEntryValue.RENDERED_LOG_ENTRY);
                Configurator.defaultConfig().writer(writer).level(Level.INFO).formatPattern("{class}").activate();

            }
        });
        mTestErrorWhileGettingSingleStackTraceElement = (Button) findComponentById(ResourceTable.Id_testErrorWhileGettingSingleStackTraceElement);
        mTestErrorWhileGettingSingleStackTraceElement.setClickedListener(new Component.ClickedListener() {
            @Override
            public void onClick(Component Component) {
                Configurator.defaultConfig().level(Level.INFO).activate();
                Logger.info("mTestErrorWhileGettingSingleStackTraceElement");

                Logger.info("mTestErrorWhileGettingSingleStackTraceElement" + ("LOGGER WARNING\\: Failed to get single stack trace element from throwable (.+)"));

                Logger.info(Logger.class.getName());
                Logger.info("testErrorWhileGettingSingleStackTraceElement", Logger.class.getSimpleName());
                Logger.info("mTestErrorWhileGettingSingleStackTraceElement" + Logger.class.getName() + "testErrorWhileGettingSingleStackTraceElement()");
                StoreWriter writer = new StoreWriter(LogEntryValue.CLASS, LogEntryValue.METHOD, LogEntryValue.RENDERED_LOG_ENTRY);
                Configurator.defaultConfig().writer(writer).level(Level.INFO).formatPattern("{class}.{method}()").activate();

                LogEntry logEntry = writer.consumeLogEntry();



            }
        });

    }

    private static final class EvilObject {

        @Override
        public String toString() {
            throw new RuntimeException();
        }

    }

    private static final class EvilWriter extends NullWriter implements Writer {

        public EvilWriter() {
            super();
        }

        public EvilWriter(final Set<LogEntryValue> requiredLogEntryValues) {
            super(requiredLogEntryValues);
        }

        @Override
        public void write(final LogEntry logEntry) {
            throw new UnsupportedOperationException();
        }

    }

    private static final class DummyWriter extends NullWriter {

        private int numberOfInits = 0;

        @Override
        public void init(final Configuration configuration) {
            ++numberOfInits;
        }

    }

    private static WritingThread findWritingThread() {
        for (Thread thread : Thread.getAllStackTraces().keySet()) {
            if (thread instanceof WritingThread) {
                return (WritingThread) thread;
            }
        }
        return null;
    }
}